/**
 * 递归函数
*/
export function orderRecurse(data, callback, { // 顺序递归
  childrenName = 'children',
  options = { close: false }
} = {}) {
  if (!data || !data.length) {
    return;
  }
  let stack = [],
    item = null,
    breakOut = false;
  for (let i = 0; i < data.length; i++) {
    stack.push(data[i]);
  }
  while (stack.length && !breakOut) {
    item = stack.shift();
    callback && callback(item, options);
    if (item[childrenName] && item[childrenName].length && !options.close) {
      stack = stack.concat(item[childrenName]);
    }
    breakOut = options.close;
  }
}
export function intoRecurse(data, callback, { // 向里递归
  childrenName = 'children',
  chainName = '',
  options = { close: false, parents: [], index: -1 }
} = {}, chains = '') {
  for (let i = 0; i < data.length; i++) {
    options.parents = data;
    options.index = i;
    if (chainName) {
      data[i].chains = chains ? chains + ',' + data[i][chainName] : chains + data[i][chainName];
    }
    callback && callback(data[i], options);
    const children = data[i][childrenName];
    if (children && children.length > 0 && !options.close) {
      intoRecurse(children, callback, { childrenName, chainName, options }, data[i].chains);
    }
    if (options.close) {
      break;
    }
  }
}

/**
 * 深拷贝
*/
export function deepCopy(obj) {
  // const _obj = Array.isArray(obj) ? [] : {};
  let _obj = {};
  switch (typeOf(obj)) {
    case 'array':
      _obj = [];
      break;
    case 'undefined':
      _obj = undefined;
      break;
    case 'null':
      _obj = null;
      break;
  }
  for (const i in obj) {
    _obj[i] = typeOf(obj[i]) === 'object' ? deepCopy(obj[i]) : obj[i];
  }
  return _obj;
}

/**
 * 判断数据类型
*/
export function typeOf(obj) {
  const toString = Object.prototype.toString,
    map = {
      '[object Boolean]': 'boolean',
      '[object Number]': 'number',
      '[object String]': 'string',
      '[object Function]': 'function',
      '[object Array]': 'array',
      '[object Date]': 'date',
      '[object RegExp]': 'regExp',
      '[object Undefined]': 'undefined',
      '[object Null]': 'null',
      '[object Object]': 'object'
    };
  return map[toString.call(obj)];
}

/**
 * 判断是否为IE内核的浏览器
*/
export function isIE() {
  const userAgent = window.navigator.userAgent;
  return userAgent.indexOf('Trident') != -1;
}

/**
 * 日期格式化
*/
export function dateFormat(fmt, d) {
  const date = d ? new Date(d) : new Date(),
    o = {
      'M+': date.getMonth() + 1, // 月份
      'd+': date.getDate(), // 日
      'H+': date.getHours(), // 小时，24小时制
      'h+': date.getHours() > 12 ? date.getHours() - 12 : date.getHours(), // 小时，12小时制
      'm+': date.getMinutes(), // 分
      's+': date.getSeconds(), // 秒
      'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
      S: date.getMilliseconds() // 毫秒
    },
    w = ['日', '一', '二', '三', '四', '五', '六'];
  if (/(y+)/.test(fmt)) {
    fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
  }
  for (const k in o) {
    if (new RegExp('(' + k + ')').test(fmt)) {
      fmt = fmt.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length));
    }
  }
  fmt = fmt.replace('{w}', w[date.getDay()]);
  return fmt;
}

/**
 * 金额格式化
*/
export function moneyFormat(num) {
  const strs = Number(num).toFixed(2).toString().split('.'),
    reg = /\d{1,3}(?=(\d{3})+$)/g;
  if (strs[1]) {
    return strs[0].replace(reg, '$&,') + '.' + strs[1];
  } else {
    return strs[0].replace(reg, '$&,');
  }
}

/**
 * 动态获取数据字典等数据
*/
export async function getDynamicData(fn, {
  value,
  valueName = 'id',
  options = {},
  autoClose = true,
  callback
}) {
  if (typeOf(fn) == 'array') {
    handleData({
      data: fn,
      value,
      valueName,
      options,
      autoClose,
      callback
    });
  } else {
    await fn.then(res => {
      if (res.code == 200) {
        const data = deepCopy(res.data);
        handleData({
          data,
          value,
          valueName,
          options,
          autoClose,
          callback
        });
      } else {
        callback && callback([]);
      }
    });
  }

  function handleData({
    data,
    value,
    valueName,
    options,
    autoClose,
    callback
  }) {
    let isDel = true;
    const arr = [];
    intoRecurse(data, (item, option) => {
      if (typeOf(value) == 'array') {
        if (value.includes(item[valueName])) {
          arr.push(item[valueName]);
          if (arr.length == value.length) {
            isDel = false;
            option.close = true;
          }
        }
      } else {
        if (item[valueName] == value) {
          isDel = false;
          if (autoClose) {
            option.close = true;
          }
        }
      }
    }, { childrenName: 'subList', ...options });
    if (typeOf(value) == 'array') {
      callback && callback(data, value.length ? isDel : false, arr);
    } else {
      callback && callback(data, value ? isDel : false, arr);
    }
    return { isDel, arr };
  }
}

/**
 * 日期选择器禁用，配合 el-date-picker 使用
*/
export function disabledDate(date, type, tag) { // 0为开始，1为结束
  const limit = tag !== undefined ? new Date(tag).getTime() : new Date().getTime();
  if (!isNaN(limit)) {
    return type ? date.getTime() < limit : date.getTime() > limit;
  }
}
/**
 * 时间选择器禁用，配合 el-time-picker 使用
*/
export function timeSelectable(type, tag, isTwelve = false) { // 0为开始，1为结束
  if (tag) {
    const l = tag.split(':').length,
      time = l == 1 ? tag + ':00:00' : l == 2 ? tag + ':00' : tag;
    return !type ? '00:00:00 - ' + time : isTwelve ? time + ' - 11:59:59' : time + ' - 23:59:59';
  }
}

/**
 * 日期、时间重新排序
 * sort：true为从小到大，false为从大到小
 * type：0为时间，1为日期
*/
export function sortTime(e, list, { key = '', sort = true, type = 0 } = {}) {
  if (e) {
    for (let i = 0; i < list.length - 1; i++) {
      if (list[i]) {
        for (let j = i + 1; j < list.length; j++) {
          const now = key ? list[i][key] : list[i],
            next = key ? list[j][key] : list[j];
          if (next) {
            const nowTime = new Date(type ? now : '2021-01-01 ' + now).getTime(),
              nextTime = new Date(type ? next : '2021-01-01 ' + next).getTime();
            if (nowTime > nextTime == sort) {
              const tmp = list[i];
              this.$set(list, i, list[j]);
              this.$set(list, j, tmp);
            }
          }
        }
      }
    }
  }
}
